// QianfanService.java
package com.xiaobao.service;

import okhttp3.*;
import org.json.JSONObject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.web.servlet.mvc.method.annotation.SseEmitter;

import java.io.IOException;
import java.util.concurrent.TimeUnit;

@Service
public class QianfanService {

    private static final Logger logger = LoggerFactory.getLogger(QianfanService.class);
    private static final OkHttpClient HTTP_CLIENT = new OkHttpClient().newBuilder()
            .readTimeout(300, TimeUnit.SECONDS) // 5分钟超时
            .build();

    @Value("${baidu.qianfan.app-id}")
    private String appId;
    @Value("${baidu.qianfan.authorization}")
    private String authorization;
    @Value("${baidu.qianfan.api-url:https://qianfan.baidubce.com/v2/app/conversation/runs}")
    private String apiUrl;

    /**
     * 流式传输AI回复
     * 该方法用于处理用户查询，并通过SSE（Server-Sent Events）流式传输AI的回复
     * 它首先检查必要的配置信息是否完整，然后构造请求体并发送POST请求
     * 接收到的流式响应会被解析并发送到前端，直到响应结束
     *
     * @param userQuery 用户的查询字符串，不能为空
     * @param emitter SseEmitter对象，用于向前端发送SSE事件
     * @param isEmitterCompleted 布尔数组，用于指示流式传输是否完成
     */
    public void streamAiReply(String userQuery, SseEmitter emitter, boolean[] isEmitterCompleted) {
        // 检查配置信息是否完整
        if (appId.isEmpty() || authorization.isEmpty()) {
            sendError(emitter, "系统错误：配置信息不完整", isEmitterCompleted);
            return;
        }
        // 检查用户查询是否为空
        if (userQuery.isEmpty()) {
            sendError(emitter, "请提供有效的问题", isEmitterCompleted);
            return;
        }

        // 构造请求体
        JSONObject requestBody = new JSONObject();
        requestBody.put("app_id", appId);
        requestBody.put("query", userQuery);
        requestBody.put("stream", true);
        requestBody.put("conversation_id", "702a3a1b-dad8-4582-bd14-35ac36ef20d9");

        // 设置媒体类型和请求体
        MediaType mediaType = MediaType.parse("application/json");
        RequestBody body = RequestBody.create(requestBody.toString(), mediaType);
        Request request = new Request.Builder()
                .url(apiUrl)
                .post(body)
                .addHeader("Content-Type", "application/json")
                .addHeader("Authorization", authorization)
                .build();

        // 发送请求并处理响应
        try (Response response = HTTP_CLIENT.newCall(request).execute()) {
            if (!response.isSuccessful()) {
                sendError(emitter, "系统错误：请求失败（状态码 " + response.code() + "）", isEmitterCompleted);
                return;
            }

            ResponseBody responseBody = response.body();
            if (responseBody == null) {
                sendError(emitter, "系统错误：响应体为空", isEmitterCompleted);
                return;
            }

            // 处理流式响应
            try (okio.BufferedSource source = responseBody.source()) {
                String line;
                while ((line = source.readUtf8Line()) != null && !isEmitterCompleted[0]) {
                    //logger.info("Received from Qianfan: {}", line);
                    if (line.startsWith("data: ")) {
                        String data = line.substring(6).trim();
                        if (!data.isEmpty()) {
                            // 发送数据到前端
                            sendData(emitter, data, isEmitterCompleted);
                        }
                    }
                }

                // 发送完成信号
                sendCompletionSignal(emitter, isEmitterCompleted);
            }
        } catch (IOException e) {
            logger.error("流式传输异常: {}", e.getMessage(), e);
            sendError(emitter, "系统错误：网络连接中断", isEmitterCompleted);
        } catch (Exception e) {
            logger.error("处理异常: {}", e.getMessage(), e);
            sendError(emitter, "系统错误：服务处理失败", isEmitterCompleted);
        }
    }

    /**
     * 向客户端发送服务器发送事件（SSE）
     * 此方法用于通过SseEmitter发送数据给客户端，同时检查Emitter是否已经完成发送任务
     *
     * @param emitter SseEmitter实例，用于发送SSE事件
     * @param data 要发送的数据
     * @param isEmitterCompleted 标记Emitter是否已完成发送任务的布尔数组
     */
    private void sendData(SseEmitter emitter, String data, boolean[] isEmitterCompleted) {
        // 检查Emitter是否已完成，如果已完成，则不再发送数据
        if (isEmitterCompleted[0]) {
            logger.debug("SseEmitter已完成，忽略发送数据");
            return;
        }

        try {
            // 发送SSE事件，包括事件ID、名称和数据
            emitter.send(SseEmitter.event()
                    .id("data")
                    .name("message")
                    .data(data));
        } catch (Exception e) {
            // 发送数据时发生异常，记录错误信息
            logger.error("发送数据失败: {}", e.getMessage());
            // 标记Emitter为已完成，防止后续继续发送数据
            isEmitterCompleted[0] = true;
        }
    }

    /**
     * 向客户端发送错误信息
     * 此方法用于在服务器发送错误信息给客户端，通过SseEmitter实现服务端发送事件（SSE）
     *
     * @param emitter SseEmitter实例，用于向客户端推送消息
     * @param errorMsg 错误信息的字符串，将被发送到客户端
     * @param isEmitterCompleted 布尔数组，用于标记SseEmitter是否已完成发送任务
     */
    private void sendError(SseEmitter emitter, String errorMsg, boolean[] isEmitterCompleted) {
        // 检查SseEmitter是否已完成任务，避免重复发送
        if (isEmitterCompleted[0]) {
            logger.debug("SseEmitter已完成，忽略发送错误");
            return;
        }

        try {
            // 发送错误消息但不标记为完成，让前端继续接收
            emitter.send(SseEmitter.event()
                    .id("error")
                    .name("message")
                    .data("{\"answer\": \"" + escapeJson(errorMsg) + "\"}"));
        } catch (Exception e) {
            // 发送错误信息时发生异常，记录日志并标记SseEmitter为完成
            logger.error("发送错误消息失败: {}", e.getMessage());
            isEmitterCompleted[0] = true;
        }
    }

    /**
     * 向指定的SseEmitter发送完成信号
     * 此方法用于通知客户端服务器发送事件流已完成
     *
     * @param emitter SseEmitter对象，用于向客户端发送事件
     * @param isEmitterCompleted 一个布尔值数组，用于标记SseEmitter是否已完成发送
     */
    private void sendCompletionSignal(SseEmitter emitter, boolean[] isEmitterCompleted) {
        // 检查SseEmitter是否已完成，避免重复发送完成信号
        if (isEmitterCompleted[0]) {
            logger.debug("SseEmitter已完成，忽略发送完成信号");
            return;
        }

        // 尝试向SseEmitter发送完成信号
        try {
            emitter.send(SseEmitter.event()
                    .id("complete")
                    .name("message")
                    .data("{\"answer\": \"\",\"complete\": true}"));
        } catch (Exception e) {
            // 如果发送过程中发生异常，记录错误日志
            logger.error("发送完成信号失败: {}", e.getMessage());
        }
    }

    /**
     * 将输入字符串进行JSON转义
     * 在JSON格式中，某些字符（如反斜杠、双引号、换行符等）具有特殊的意义，直接使用这些字符会导致JSON解析错误
     * 此方法旨在对这些特殊字符进行转义，以确保字符串可以安全地嵌入到JSON中
     *
     * @param input 待转义的字符串如果输入为null，将返回空字符串
     * @return 转义后的字符串如果输入为空，则返回空字符串
     */
    private String escapeJson(String input) {
        if (input == null) {
            // 当输入为null时，返回空字符串，避免NullPointerException
            return "";
        }
        // 对字符串中的特殊字符进行JSON转义：
        // 1. 反斜杠(\)转义为双反斜杠(\\)
        // 2. 双引号(")转义为(\")
        // 3. 换行符(\n)、回车符(\r)和制表符(\t)分别转义为对应的转义序列
        return input.replace("\\", "\\\\")
                .replace("\"", "\\\"")
                .replace("\n", "\\n")
                .replace("\r", "\\r")
                .replace("\t", "\\t");
    }
}